use io::BufReader as Reader;
use std::collections::HashMap;
use std::fs::File;
use std::io::{self, BufRead};

pub fn converter(input: &str) -> String {
    let map1 = load_pinyin("kMandarin.txt").unwrap();
    let map2 = load_pinyin_to_wade_giles("pinyin_to_wade_giles.txt");
    let mut res = String::new();
    for c in input.chars() {
        let pinyin = match map1.get(&c) {
            Some(p) => remove_tone(p),
            None => continue, 
        };
        let wade_giles = match map2.get(pinyin.as_str()) {
            Some(wg) => wg,
            None => continue, 
        };
        if !res.is_empty() {
            res.push(' ');
        }
        res.push_str(wade_giles);
    }
    // make first letter uppercase
    let mut chars = res.chars();
    if let Some(first) = chars.next() {
        let mut res = first.to_uppercase().collect::<String>();
        res.push_str(chars.as_str());
        return res;
    }
    res
}

fn remove_tone(pinyin: &String) -> String {
    pinyin
        .replace("ā", "a")
        .replace("á", "a")
        .replace("ǎ", "a")
        .replace("à", "a")
        .replace("ē", "e")
        .replace("é", "e")
        .replace("ě", "e")
        .replace("è", "e")
        .replace("ī", "i")
        .replace("í", "i")
        .replace("ǐ", "i")
        .replace("ì", "i")
        .replace("ō", "o")
        .replace("ó", "o")
        .replace("ǒ", "o")
        .replace("ò", "o")
        .replace("ū", "u")
        .replace("ú", "u")
        .replace("ǔ", "u")
        .replace("ù", "u")
        .replace("ǘ", "u")
        .replace("ǚ", "u")
        .replace("ǜ", "u")
        .replace("ü", "u")
        .replace("ń", "n")
        .replace("ň", "n")
        .replace("ǹ", "n")
}

// load pinyin data from
// https://github.com/mozillazg/pinyin-data/blob/889cde8bb0769747849f1d26bfc60c18efee1db3/kMandarin.txt
fn load_pinyin(file_path: &str) -> io::Result<HashMap<char, String>> {
    let mut map = HashMap::new();
    let file = File::open(file_path)?;
    let reader = Reader::new(file);

    for line in reader.lines() {
        let line = line?;
        let (cp, pinyin) = match line.split_once(":") {
            Some(pair) => pair,
            None => continue,
        };
        let cp = cp.trim();
        let (pinyin, _) = match pinyin.split_once("#") {
            Some(pair) => pair,
            None => continue,
        };
        let pinyin = pinyin.trim();
        let hex = match cp.strip_prefix("U+") {
            Some(h) => h,
            None => continue,
        };
        let hex = match u32::from_str_radix(hex, 16) {
            Ok(h) => h,
            Err(_) => continue,
        };
        let c = match char::from_u32(hex) {
            Some(c) => c,
            None => continue,
        };
        // 插入到 `map` 中
        map.insert(c, pinyin.to_string());
    }

    Ok(map)
}

fn load_pinyin_to_wade_giles(file_path: &str) -> HashMap<String, String> {
    let mut map = HashMap::new();
    let file = File::open(file_path).unwrap();
    let reader = Reader::new(file);

    for line in reader.lines() {
        let line = line.unwrap();
        if let Some((pinyin, wade_giles)) = line.split_once(" ") {
            map.insert(pinyin.to_string(), wade_giles.to_string());
        }
    }
    map
}
